package com.xbongbong.paas.controller.dingtalk;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.manager.DingtalkManager;
import com.xbongbong.paas.service.LoginService;
import com.xbongbong.paas.service.SnsLoginService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.ApiHttpRequestUtils;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.util.URLEncodeUtils;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.dingtalk.pojo.dto.GenerateNonceDTO;
import com.xbongbong.pro.dingtalk.pojo.dto.SnsUserInfoDTO;
import com.xbongbong.pro.dingtalk.pojo.vo.GenerateNonceVO;
import com.xbongbong.pro.dingtalk.pojo.vo.ScanLoginVO;
import com.xbongbong.pro.dingtalk.pojo.vo.SnsUserInfoVO;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ThirdPartyUsageErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.login.pojo.dto.AuthorizeDTO;
import com.xbongbong.pro.login.pojo.vo.AutoLoginVO;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.sys.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Objects;

/**
 * 第三方应用授权相关
 * @author chy
 * @ProjectName
 * @Description: 连接相关共用对外接口
 * @date 2019/1/24 15:34
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/dingtalk/open")
public class DingtalkOpenController {
    private static final Logger LOG = LoggerFactory.getLogger(DingtalkOpenController.class);

    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private SnsLoginService snsLoginService;
    @Resource
    private DingtalkManager dingtalkManager;
    @Resource
    private LoginService loginService;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private UserModel userModel;




    /**
     * 判断公司及用户是否有权开通
     */
    @RequestMapping(value = "/permissionCheck", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String permissionCheck(@RequestBody JSONObject jsonObject, BindingResult br) throws Exception {
        XbbResponse<BaseVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {

            try {
                String corpid = jsonObject.getString("corpid");
                String userId = jsonObject.getString("userId");
                if ( !isEffectiveCompany(corpid) ) {
                    throw new XbbException(ThirdPartyUsageErrorCodeEnum.API_ERROR_900003);
                }

                if ( !isEffectiveUser(corpid, userId) ) {
                    throw new XbbException(ThirdPartyUsageErrorCodeEnum.API_ERROR_900004);
                }
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
            BaseVO baseVO = new BaseVO();
            response = new XbbResponse<>(baseVO);
        }
        return JSON.toJSONString(response);
    }

    /**
     * 公司是否有效，判断company是否存在
     * true:有效 false:无效
     * @param corpid
     * @return
     * 创建时间 2020/1/19 10:57 AM
     * 修改时间 2020/1/19 10:57 AM
     * @author chy
     */
    private boolean isEffectiveCompany(String corpid) {
        CompanyEntity company = companyModel.getByKey(corpid);
        if ( Objects.isNull(company) ) {
            return false;
        }
        return true;
    }

    /**
     * 操作人是否有权限，判断userId是否是管理员或老板
     * true:有 false:无
     * @param corpid 操作人的corpid
     * @param userId 操作人的userId
     * @return
     * 创建时间 2020/1/19 11:06 AM
     * 修改时间 2020/1/19 11:06 AM
     * @author chy
     */
    private boolean isEffectiveUser(String corpid, String userId) {
        UserEntity userEntity = userModel.getByKey(userId, corpid);

        if ( userEntity.isOriAdmin() ) {
            return true;
        }

        return false;
    }

    /**
     * 获取pro扫码登录gotoUrl
     */
    @RequestMapping(value = "/scanLogin", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String scanLogin(@RequestBody JSONObject jsonObject, BindingResult br) throws Exception {
        XbbResponse<ScanLoginVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            ScanLoginVO scanLoginVO = new ScanLoginVO();
            String scanCodeUrl;
            if ("xbbProDev".equals(ProBaseConfig.getProjectName()) || "xbbProOmsDev".equals(ProBaseConfig.getProjectName())) {
                scanCodeUrl = "mkbx-scan-code.html";
            } else {
                scanCodeUrl = "pro/mkbx-scan-code.html";
            }

            String gotoUrl = "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid="
                    + proBaseConfig.getScanAppId()
                    + "&response_type=code&scope=snsapi_login&state=STATE&redirect_uri="
                    + ProBaseConfig.getDingtalkFrontUrl()
                    + scanCodeUrl;
            scanLoginVO.setGotoUrl(gotoUrl);
            scanLoginVO.setGotoUrlEncode(URLEncodeUtils.encodeURL(gotoUrl));
            response = new XbbResponse<>(scanLoginVO);
        }
        return JSON.toJSONString(response);
    }

    /**
     * 扫码登录获取登录用户信息
     */
    @RequestMapping(value = "/userInfo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String userInfo(@RequestBody @Valid SnsUserInfoDTO snsUserInfoDTO, BindingResult br) throws Exception {
        XbbResponse<SnsUserInfoVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                SnsUserInfoVO snsUserInfoVO = snsLoginService.snsUserInfo(snsUserInfoDTO.getCode(), snsUserInfoDTO.getCorpid());
                response = new XbbResponse<>(snsUserInfoVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }


    @RequestMapping(value = "/generateNonce", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String generateNonce(@RequestBody @Valid GenerateNonceDTO generateNonceDTO, BindingResult br) throws Exception {
        XbbResponse<GenerateNonceVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                GenerateNonceVO generateNonceVO = dingtalkManager.generateNonce(generateNonceDTO);
                response = new XbbResponse<>(generateNonceVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }


    @RequestMapping(value = "/authorize", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String authorize(@RequestBody @Valid AuthorizeDTO authorizeDTO, BindingResult br, HttpServletRequest request, HttpServletResponse httpResponse) throws Exception {
        XbbResponse<AutoLoginVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                AutoLoginVO autoLoginVO = loginService.autoLogin(authorizeDTO, request, httpResponse);

                LOG.info("autoLoginVO:" + autoLoginVO);

                if (Objects.isNull(autoLoginVO.getCode()) ||
                        Objects.equals(autoLoginVO.getCode(), ErrorCodeEnum.API_SUCCESS.getCode())) {

                    String corpid = autoLoginVO.getCorpid();
                    String userId = autoLoginVO.getUserId();


                    JSONObject header = new JSONObject();
                    header.put("secret", PaasConstant.API_SECRET);
                    header.put("openAppId", StringUtil.toInt(authorizeDTO.getOpenAppId(), null));

                    String url = ProBaseConfig.getApiUrl() + "/pro/v1/app/companyAuthorize";
                    JSONObject data = new JSONObject();
                    data.put("corpid", corpid);
                    data.put("userId", userId);
                    LOG.info("header:" + header);
                    LOG.info("url:" + url);
                    LOG.info("data:" + data);
                    String ret = ApiHttpRequestUtils.post(header, url, data.toJSONString());
                    JSONObject retJson = JSON.parseObject(ret);
                    Integer code = retJson.getInteger("code");
                    if (!Objects.equals(code, ErrorCodeEnum.API_SUCCESS.getCode())) {
                        autoLoginVO.setCode(code);
                        autoLoginVO.setMsg(retJson.getString("msg"));
                    }
                }

                response = new XbbResponse<>(autoLoginVO);
            } catch (XbbException xe) {
                response = new XbbResponse<>(xe);
            }
        }
        return JSON.toJSONString(response);
    }



}
